﻿#region summary

// Copyright (c)  YISH. All rights reserved.
// Licensed under the MIT License, See License.txt in the project root for license information.

#endregion

using System;
using NSQL.Expressions;
using NSQL.Generator;
using NSQL.Sharpen;

namespace NSQL.Statements
{
    public class SelectStatement : ISelectStatement
    {
        private SortingCollection _sortingClause;
        private GroupCollection _groupClause;
        private TableSourceCollection _tableSource;
        private SelectElementCollection _elements;
        
        /// <summary>
        /// With Statement
        /// </summary>
        public FactoringSelectStatementCollection WithStatements { get; set; } =
            new FactoringSelectStatementCollection();

        /// <summary>
        /// Selected elements
        /// </summary>
        public SelectElementCollection Elements
        {
            get => _elements ?? (_elements = new SelectElementCollection());
            set => _elements = value ?? throw new ArgumentNullException(nameof(value));
        }

        public TableSourceCollection TableSources
        {
            get => _tableSource ?? (_tableSource = new TableSourceCollection());
            set => _tableSource = value ?? throw new ArgumentNullException(nameof(value));
        }

        public IPredicateExpression Predicate { get; set; }

        public GroupCollection GroupClause
        {
            get => _groupClause ?? (_groupClause = new GroupCollection());
            set => _groupClause = value ?? throw new ArgumentNullException(nameof(value));
        }

        public SortingCollection SortingClause
        {
            get => _sortingClause ?? (_sortingClause = new SortingCollection());
            set => _sortingClause = value ?? throw new ArgumentNullException(nameof(value));
        }

        public int Skip { get; set; }
        public int Limit { get; set; }

        public bool CanOptimized =>
            Elements.Count == 1 && TableSources.Count == 1 &&
            Elements[0] == SelectElement.Asterisk  &&
            TableSources[0] is ISelectStatement &&
            Skip <= 0 && Limit <= 0 &&
            (_sortingClause == null || _sortingClause.Count == 0) &&
            (_groupClause == null || _groupClause.Count == 0 && _groupClause.Having is null);

        /// <inheritdoc />
        public Identifier Alias { get; set; }


        public string Accept(ISqlGenerator generator) => generator.Generate(this);
        public object Tag { get; set; }

        object IDeepClone.DeepCopy()
        {
            return new SelectStatement()
            {
                _elements = _elements.DeepClone(),
                _tableSource = _tableSource.DeepClone(),
                _sortingClause = _sortingClause.DeepClone(),
                _groupClause = _groupClause.DeepClone(),
                Predicate = Predicate.DeepClone(),
                Alias = Alias,
                Skip = Skip,
                Limit = Limit,
                Tag = Tag
            };
        }
    }
}